package br.uff.es2.xadrez.gui;

/**
 *
 * @author Luiz Nunes
 */
import br.uff.es2.xadrez.core.Board;
import br.uff.es2.xadrez.core.Piece;
import br.uff.es2.xadrez.core.Queen;
import br.uff.es2.xadrez.core.exceptions.CheckMateException;
import br.uff.es2.xadrez.core.exceptions.PromocaoDePecasException;
import br.uff.es2.xadrez.core.exceptions.RoqueException;
import br.uff.es2.xadrez.core.exceptions.WrongMoveException;
import br.uff.es2.xadrez.ia.InteligenciaArtificial;
import br.uff.es2.xadrez.ia.OutraIa;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import javax.swing.*;

public class Tabuleiro extends JFrame implements MouseListener,
        MouseMotionListener {

    Board engineBoard;
    InteligenciaArtificial ia;
    OutraIa outraIa;
    JLayeredPane layeredPane;
    public static JPanel chessBoard;
    JLabel chessPiece;
    int xAdjustment;
    int yAdjustment;
    int sourceX;
    int sourceY;
    Point ultimaPosicaoJogada;
    JLabel pequenoRoque;
    private static final int BOARD_DIMENSION_X = 600;
    private static final int BOARD_DIMENSION_Y = 600;
//    private boolean changeTurn = false;
    private int[] posicaoEspecial;
    private boolean isCheckMate = false;

    public Tabuleiro() {
        Dimension boardSize = new Dimension(BOARD_DIMENSION_X, BOARD_DIMENSION_Y);

        //  Use a Layered Pane for this this application
        layeredPane = new JLayeredPane();
        getContentPane().add(layeredPane);
        layeredPane.setPreferredSize(boardSize);
        layeredPane.addMouseListener(this);
        layeredPane.addMouseMotionListener(this);

        engineBoard = new Board();
        ia = new InteligenciaArtificial();
        outraIa = new OutraIa();
        //adiciona o tabuleiro ao Panel

        chessBoard = new JPanel();
        layeredPane.add(chessBoard, JLayeredPane.DEFAULT_LAYER);
        chessBoard.setLayout(new GridLayout(8, 8));
        chessBoard.setPreferredSize(boardSize);
        chessBoard.setBounds(0, 0, boardSize.width, boardSize.height);

        for (int i = 0; i < 64; i++) {
            JPanel square = new JPanel(new BorderLayout());
            chessBoard.add(square);

            int row = (i / 8) % 2;
            if (row == 0) {
                square.setBackground(i % 2 == 0 ? Color.white : Color.gray);
            } else {
                square.setBackground(i % 2 == 0 ? Color.gray : Color.white);
            }
        }

        //adiciona as pecas no tabuleiro
        preencherTabuleiro();
        //JLabel piece = new JLabel(new ImageIcon("Black knight 2d.png"));
        //JPanel panel = (JPanel) chessBoard.getComponent(62);
        //panel.add(piece);
        JMenu jogoMenu = new JMenu("Jogo");
        JMenuItem salvar = new JMenuItem("Salvar");
        JMenuItem sair = new JMenuItem("Sair");
        jogoMenu.add(salvar);
        jogoMenu.add(sair);
        JMenuBar menuBar = new JMenuBar();
        setJMenuBar(menuBar);
        menuBar.add(jogoMenu);
    }

    public void mousePressed(MouseEvent e) {
        chessPiece = null;
        Component c = chessBoard.findComponentAt(e.getX(), e.getY());

        if (c instanceof JPanel) {
            return;
        }
        if (c == null) {
            return;
        }
        Point parentLocation = c.getParent().getLocation();
        sourceX = parentLocation.x;
        sourceY = parentLocation.y;
        xAdjustment = sourceX - e.getX();
        yAdjustment = sourceY - e.getY();

        chessPiece = (JLabel) c;
        chessPiece.setLocation(sourceX, sourceY);
        chessPiece.setSize(chessPiece.getWidth(), chessPiece.getHeight());
        layeredPane.add(chessPiece, JLayeredPane.DRAG_LAYER);
    }

    //Move the chess piece around
    public void mouseDragged(MouseEvent me) {
        if (chessPiece == null) {
            return;
        }
        if (me.getX() > 10) {
            chessPiece.setLocation(me.getX() + xAdjustment, me.getY() + yAdjustment);
//            System.out.println("LOCALIZACAOOOOOOOOO " + me.getY());
        } else {
            // System.out.println("IMPOSSIVELLLLLLLLLLLLLLLLLLL ");
            //System.out.println("LOCALIZACAOOOOOOOOOOOOOOOOOOOOOOOOO " + me.getX());
        }
    }

    //Drop the chess piece back onto the chess board
    public void mouseReleased(MouseEvent e) {

        if (isCheckMate) {
            Component teste2 = chessBoard.findComponentAt(sourceX, sourceY);
            Container parent = (Container) teste2;
            parent.add(chessPiece);
            chessPiece.setVisible(true);
            chessBoard.invalidate();
            return;
        }

        if (chessPiece == null) {
            return;
        }

        chessPiece.setVisible(false);
        Component c = chessBoard.findComponentAt(e.getX(), e.getY());

        if (c != null) {

            Container parent;
            double destX;
            double destY;

            if (c.getLocation().x == 0 && c.getLocation().y == 0) {
                destX = e.getX();
                destY = e.getY();
            } else {
                destX = c.getLocation().x;
                destY = c.getLocation().y;
            }

            int[] source = convertToChessPosition(sourceY, sourceX);
            int[] destination = convertToChessPosition(destY, destX);

            try {
                doMovement(source, destination);

            } catch (WrongMoveException ex) {
                //               changeTurn = false;
                Component teste2 = chessBoard.findComponentAt(sourceX, sourceY);
                parent = (Container) teste2;
                parent.add(chessPiece);
                chessPiece.setVisible(true);
                chessBoard.invalidate();
                return;
            } catch (CheckMateException ex) {
                System.out.println("MATE");
                isCheckMate = true;
            }

            if (c instanceof JLabel) {
                parent = c.getParent();
                parent.remove(0);
                parent.add(chessPiece);
            } else {
                parent = (Container) c;
                parent.add(chessPiece);
            }
        } else {
            Component teste2 = chessBoard.findComponentAt(sourceX, sourceY);
            Container parent = (Container) teste2;
            parent.add(chessPiece);
        }
//        if (changeTurn)
        ultimaPosicaoJogada = e.getPoint();
        chessPiece.setVisible(true);
        chessBoard.validate();
        doCPUMovement();
    }

    private void doMovement(int[] source, int[] destination) throws WrongMoveException, CheckMateException {
        try {
            posicaoEspecial = getEngineBoard().move(source, destination);
//                changeTurn = true;
            if (posicaoEspecial != null) {
                posicaoEspecial[0] = (posicaoEspecial[0] + 1) * (BOARD_DIMENSION_X / 8);
                posicaoEspecial[1] = (posicaoEspecial[1] + 1) * (BOARD_DIMENSION_Y / 8);
                Component remover = chessBoard.findComponentAt(ultimaPosicaoJogada);
//                    parent = remover.getParent();
//                    parent.remove(0);
//                    parent.add(chessPiece);
                JLabel pecaMorta = (JLabel) remover;
                pecaMorta.setLocation(posicaoEspecial[0], posicaoEspecial[1]);
                pecaMorta.setSize(chessPiece.getWidth(), chessPiece.getHeight());
                pecaMorta.setVisible(false);
            }
        } catch (RoqueException ex) {

            int posicaoAntigaTorre[] = {(Board.roque.getPosicaoAntigaTorre()[0] * (BOARD_DIMENSION_X / 8)),
                (Board.roque.getPosicaoAntigaTorre()[1] * (BOARD_DIMENSION_Y / 8))};
            int posicaoNovaTorre[] = {(Board.roque.getPosicaoNovaTorre()[0] * (BOARD_DIMENSION_X / 8)),
                (Board.roque.getPosicaoNovaTorre()[1] * (BOARD_DIMENSION_Y / 8))};


            Component remover = chessBoard.findComponentAt(posicaoAntigaTorre[1], posicaoAntigaTorre[0]);
            Point parentLocation = remover.getParent().getLocation();

            JLabel teste = (JLabel) remover;
            teste.setLocation(posicaoNovaTorre[1], parentLocation.x);
            teste.setSize(chessPiece.getWidth(), chessPiece.getHeight());
            layeredPane.add(teste, JLayeredPane.DRAG_LAYER);


            Component ad = chessBoard.findComponentAt(posicaoNovaTorre[1], posicaoNovaTorre[0]);
            Container p = (Container) ad;
            p.add(teste);
            chessBoard.validate();
        } catch (PromocaoDePecasException promocao) {

//            if (engineBoard.getTurn() == Piece.Color.WHITE) {
//                JPanel panel = (JPanel) Tabuleiro.chessBoard.getComponent(PromocaoPecas.novaPosicao[1]);
//                panel.removeAll();
//                Board.board[PromocaoPecas.novaPosicao[0]][PromocaoPecas.novaPosicao[1]] = new Queen(Piece.Color.BLACK, "img\\rainha.png");
//                JLabel pieceLabel = new JLabel(new ImageIcon("img\\rainha.png"));
//                panel.add(pieceLabel);
//            } else {
                JFrame teste = new PromocaoPecas();
                teste.setVisible(true);
                teste.setTitle("Promoção de peças");
                teste.setVisible(true);
                teste.setSize(500, 200);
                teste.setLocationRelativeTo(null);
                chessPiece.removeAll();
//            }
//            chessPiece = Board.promocao.getPromocao();
//            (JPanel) chessBoard.getComponent(line * 8 + column);
//            JLabel pieceLabel = new JLabel(new ImageIcon(piece.getImageFilePath()));
//                    JPanel panel = chessBoard.getComponent(line * 8 + column);
//                            getJPanel(i, j);
//                    panel.add(pieceLabel);


        }
    }

    private void doCPUMovement() {
        if (isCheckMate) {
            return;
        }

//        int[][] movement = ia.move(getEngineBoard());
        int[][] movement = outraIa.move(getEngineBoard());
        try {
            doMovement(movement[0], movement[1]);
        } catch (CheckMateException ex) {
            isCheckMate = true;
        } catch (WrongMoveException ex) {
            System.out.println(ex.getMessage());
            doCPUMovement();
            return;
        }

        int posicaoAntiga[] = {(movement[0][0] * (BOARD_DIMENSION_X / 8)),
            (movement[0][1] * (BOARD_DIMENSION_Y / 8))};
        int posicaoNova[] = {(movement[1][0] * (BOARD_DIMENSION_X / 8)),
            (movement[1][1] * (BOARD_DIMENSION_Y / 8))};
        Component remover = chessBoard.findComponentAt(posicaoAntiga[1], posicaoAntiga[0]);

        Component newPosition = chessBoard.findComponentAt(posicaoNova[1], posicaoNova[0]);
        if (newPosition instanceof JLabel) {
            Container parent = newPosition.getParent();
            parent.remove(0);
        }

        JLabel piece = (JLabel) remover;
        piece.setLocation(posicaoNova[1], posicaoNova[0]);
        piece.setSize(chessPiece.getWidth(), chessPiece.getHeight());
        layeredPane.add(piece, JLayeredPane.DRAG_LAYER);

        Component ad = chessBoard.findComponentAt(posicaoNova[1], posicaoNova[0]);
        Container p = (Container) ad;
        p.add(piece);
        ultimaPosicaoJogada = ad.getLocation();
        chessBoard.validate();

    }

    private int[] convertToChessPosition(double x, double y) {
        int[] chessPosition = {(new Double(x)).intValue() / (BOARD_DIMENSION_X / 8), (new Double(y)).intValue() / (BOARD_DIMENSION_Y / 8)};
        return chessPosition;
    }

    public void mouseClicked(MouseEvent e) {
    }

    public void mouseMoved(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public static void main(String[] args) {
        JFrame frame = new Tabuleiro();
        frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        frame.pack();
        frame.setResizable(true);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.setTitle("Engenharia de Software II");
        frame.setBackground(Color.BLACK);
        frame.setResizable(true);
    }

    private void preencherTabuleiro() {
        Piece[][] board = getEngineBoard().getBoard();
        for (int i = 0; i < board.length; i++) {
            Piece[] pieces = board[i];
            for (int j = 0; j < pieces.length; j++) {
                Piece piece = pieces[j];
                if (piece != null) {
                    URL urlImg = this.getClass().getClassLoader().getResource(piece.getImageFilePath());
                    JLabel pieceLabel = null;
                    if(urlImg != null)
                        pieceLabel = new JLabel(new ImageIcon(urlImg));
                    else
                        pieceLabel = new JLabel(new ImageIcon(piece.getImageFilePath()));
                    JPanel panel = getJPanel(i, j);
                    panel.add(pieceLabel);
                }
            }

        }
    }

    private JPanel getJPanel(int line, int column) {
        return (JPanel) chessBoard.getComponent(line * 8 + column);
    }

    /**
     * @return the engineBoard
     */
    public Board getEngineBoard() {
        return engineBoard;
    }

    /**
     * @param engineBoard the engineBoard to set
     */
    public void setEngineBoard(Board engineBoard) {
        this.engineBoard = engineBoard;
    }
}
